package commons;
/**
 * Calculates the pow(x, x)
 */
public class CalculatorShewetaank {
	private static double m = 0;
	private static int intgr = 0;
	private static int p = 0;
	
	public Double getUserValue(String inputValue) {
		double value = 0;
		if(isInteger(inputValue)){
			getIntegerValue(inputValue);
			
			if(intgr < 0){
				intgr = -intgr;
				if(intgr%2 == 0){
					value = -(1.0/calculatePower(intgr));
				}
				else{
					value = -(1.0/calculatePower(intgr));
				}
			}
			else if(intgr > 0){
				value = calculatePower(intgr);
			}
		}
		else if(isDouble(inputValue)){
			getDoubleValue(inputValue);
			
			reduceNumber(m, 0);
	        
	        double squareRoot = findSquareRoot(m);
	        
			double naturalLog = (2*calculateLog(squareRoot) + (2.302585*p));

			value = calculateExpression(naturalLog, m);

		}	
		return value;
	}

	private boolean isDouble(String inputValue) {
		try{
			Double.parseDouble(inputValue);
			return true;
		}
		catch(NumberFormatException e){
			System.out.println(e.getMessage());
			return false;
		}
	}

	private boolean isInteger(String inputValue) {
		try{
			Integer.parseInt(inputValue);
			return true;
		}
		catch(NumberFormatException e){
			System.out.println(e.getMessage());
			return false;
		}
		
	}

	private static void getIntegerValue(String value) {
		intgr = Integer.parseInt(value);
	}
	private static void getDoubleValue(String value){
	    m = Double.parseDouble(value);
	}

	private static double calculateExpression(double base, double power) {
		double finalValue = 0;
		double transValue = base*power;
		double e = 2.7182818284590;
		int integerPart = (int) transValue;
		double fractionalPart = transValue - integerPart;

		if(fractionalPart < 0){
			finalValue = 1/calculatePower(e, integerPart) * (1 + fractionalPart + 
					     (calculatePower(fractionalPart, 2)/2) + 
					     (calculatePower(fractionalPart, 3)/6) +
					     (calculatePower(fractionalPart, 4)/24) +
					     (calculatePower(fractionalPart, 5)/120));                
		}
		else{
			finalValue = calculatePower(e, integerPart) * (1 + fractionalPart + 
                         (calculatePower(fractionalPart, 2)/2) + 
                         (calculatePower(fractionalPart, 3)/6) +
                         (calculatePower(fractionalPart, 4)/24) +
                         (calculatePower(fractionalPart, 5)/120));
		}
		return finalValue;
	}

	private static double calculateLog(double number) {
		
		/** y with precision of +/- 0.0008 */
		double y = (number -1)/(number + 1);
		
		double logValue = 2*(y + (calculatePower(y, 3)/3) + (calculatePower(y, 5)/5) + (calculatePower(y, 7)/7));
		return logValue;
	}

	private static Double calculatePower(double y, int i) {
		
		double powerValue = 1.0;
		for(int j =0; j< i; j++){
		powerValue *= y;
		}
		return powerValue;
	}
	
	private static int calculatePower(int i){
		int powerValue = 1;
		for(int j=0; j<i; j++){
			powerValue *= i;
		}
		return powerValue;
	}

	private static double findSquareRoot(double number) {
		boolean isPositive = true;
		double g1;
		if(number == 0){
			return number;
		}
		else if(number<0){
			number = -number;
			isPositive = false;
		}
		/** finding the square root */
		double squareRoot = number/2;
		
		do{
			g1 = squareRoot;
			squareRoot = (g1 + (number/g1))/2;
		}
		while((g1-squareRoot)!= 0);
		if(!isPositive){
			return squareRoot;
		}
		return squareRoot;
	}
	private static void reduceNumber(double x, int i) {
		p = i;
		if(x >= 10){		
		m = x/10;
		p++;
		reduceNumber(m, p);
		}
	}
}
